/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef INCLUDE_SPINLOCK_H
#define INCLUDE_SPINLOCK_H

#ifndef ASSEMBLY

#include <arch_spinlock.h>
#include <Semag.h>
#include <irq.h>


/**
 * @brief spinlock init.
 *
 * @param[in] spinlock spinlock address.
 */
static inline void spin_lock_init(spin_lock_t *spinlock)
{
    arch_spin_lock_init(spinlock);
}

/**
 * @brief spin lock.
 *
 * @param[in] spinlock spinlock address.
 */
static inline void spin_lock(spin_lock_t *spinlock)
{
    arch_spin_lock(spinlock);
}

/**
 * @brief spin trylock.
 *
 * @param[in] spinlock spinlock address.
 * @return try lock result.
 */
static inline int spin_trylock(spin_lock_t *spinlock)
{
    return arch_spin_trylock(spinlock);
}

/**
 * @brief spin unlock.
 *
 * @param[in] spinlock spinlock address.
 */
static inline void spin_unlock(spin_lock_t *spinlock)
{
    arch_spin_unlock(spinlock);
}

/**
 * @brief spin lock with irq save
 *
 * @param[in] spinlock spinlock address.
 * @return old irq state.
 */
static inline irq_state_t spin_lock_irqsave(spin_lock_t *spinlock)
{
    irq_state_t state = arch_irq_save();
    spin_lock(spinlock);
    return state;
}

/**
 * @brief spin unlock with irq restore
 *
 * @param[in] spinlock spinlock address.
 * @param[in] state old irq state.
 */
static inline void spin_unlock_irqrestore(spin_lock_t *spinlock, irq_state_t state)
{
    spin_unlock(spinlock);
    arch_irq_restore(state);
}

/**
 * @brief spin lock based on semaphore gate.
 *
 * @param[in] gate_idx Gate number to lock.
 */
static inline void semag_spin_lock(uint32 gate_idx)
{
    while(SEMAG_E_FAIL == sdrv_semag_trylock(gate_idx))
    {
        __asm volatile("wfe");
    }
}

/**
 * @brief spin trylock based on semaphore gate.
 *
 * @param[in] gate_idx Gate number to lock.
 * @return try lock result.
 */
static inline lld_status_t semag_spin_trylock(uint32 gate_idx)
{
    return sdrv_semag_trylock(gate_idx);
}

/**
 * @brief spin unlock based on semaphore gate.
 *
 * @param[in] gate_idx Gate number to lock.
 */
static inline void semag_spin_unlock(uint32 gate_idx)
{
    sdrv_semag_unlock(gate_idx);
    __asm volatile("sev");
}

/**
 * @brief semag spin lock with irq save
 *
 * @param[in] gate_idx Gate number to lock.
 * @return old irq state.
 */
static inline irq_state_t semag_spin_lock_irqsave(uint32 gate_idx)
{
    irq_state_t state = arch_irq_save();
    semag_spin_lock(gate_idx);
    return state;
}

/**
 * @brief semag spin unlock with irq restore
 *
 * @param[in] gate_idx Gate number to lock.
 * @param[in] state old irq state.
 */
static inline void semag_spin_unlock_irqrestore(uint32 gate_idx, irq_state_t state)
{
    semag_spin_unlock(gate_idx);
    arch_irq_restore(state);
}


#endif

#endif
